package com.client.utils;

import com.client.sm9.gm.sm9.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/*
 *序列化与反序列化工具类
 *
 */
@Component
@Slf4j
public class Utils {
    static SM9Curve sm9Curve = new SM9Curve();

    //序列化工具
    public static byte[] getByteFromMap(Map<String, String> map) {
        byte[] bytes = null;
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(5120);
            ObjectOutputStream stream = new ObjectOutputStream(outputStream);
            stream.writeObject(map);
            outputStream.flush();   //缓冲流
            outputStream.close();   //关闭流

            bytes = outputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bytes;
    }

    //序列化工具
    public static byte[] getByteFromObjectMap(Map<String, Object> map) {
        byte[] bytes = null;
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(5120);
            ObjectOutputStream stream = new ObjectOutputStream(outputStream);
            stream.writeObject(map);
            outputStream.flush();   //缓冲流
            outputStream.close();   //关闭流

            bytes = outputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bytes;
    }

    //反序列化工具
    public static Map<String, String> getMapFromByte(byte[] bytes) {
        try {
            //反序列化
            ByteArrayInputStream stream1 = new ByteArrayInputStream(bytes);
            ObjectInputStream stream2 = new ObjectInputStream(stream1);
            Object o = stream2.readObject();

            return (Map<String, String>) o;
        } catch (Exception e) {
//            e.printStackTrace();
        }
        return null;
    }

    public static Map<String, Object> getObjectMapFromByte(byte[] bytes) throws IOException, ClassNotFoundException {
        //反序列化
        ByteArrayInputStream stream1 = new ByteArrayInputStream(bytes);
        ObjectInputStream stream2 = null;
        stream2 = new ObjectInputStream(stream1);
        Object o = stream2.readObject();

        return (Map<String, Object>) o;
    }

    //私钥序列化 PrivateKey
    public static byte[] serializePrivateKey(PrivateKey privateKey) {
        return privateKey.toByteArray();
    }

    //私钥反序列化 deserialize
    public static PrivateKey deserializePrivateKey(byte[] bytes) {
        return PrivateKey.fromByteArray(sm9Curve, bytes);
    }

    //签名结果序列化
    public static byte[] serializeResultSignature(ResultSignature resultSignature) {
        return resultSignature.toByteArray();
    }

    //签名结果反序列化
    public static ResultSignature deserializeResultSignature(byte[] bytes) {
        return ResultSignature.fromByteArray(sm9Curve, bytes);
    }

    //TempKeyPair 序列化
    public static byte[] serializeG1KeyPair(G1KeyPair g1KeyPair) {
        return g1KeyPair.toByteArray();
    }

    //G1KeyPair 反序列化
    public static G1KeyPair deserializeG1KeyPair(byte[] bytes) {
        return G1KeyPair.fromByteArray(sm9Curve, bytes);
    }

    //ResultKeyExchange 序列化
    public static byte[] serializeResultKeyExchange(ResultKeyExchange resultKeyExchange) {
        Map<String, Object> map = new HashMap<>();
        map.put("SK", resultKeyExchange.getSK());
        map.put("SB", resultKeyExchange.getSB1());
        map.put("SA", resultKeyExchange.getSA2());
        return getByteFromObjectMap(map);
    }

    //ResultKeyExchange 反序列化
    public static ResultKeyExchange deserializeResultKeyExchange(byte[] bytes) {
        try {
            Map<String, Object> map = getObjectMapFromByte(bytes);
            byte[] sk = (byte[]) map.get("SK");
            byte[] sb = (byte[]) map.get("SB");
            byte[] sa = (byte[]) map.get("SA");
            return new ResultKeyExchange(sk, sa, sb);
        } catch (Exception e) {
            log.info("ResultKeyExchange 反序列化失败");
        }
        return null;
    }

    //Date
    public static byte[] getByteFromDate(Date date) {
        byte[] bytes = null;
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(5120);
            ObjectOutputStream stream = new ObjectOutputStream(outputStream);
            stream.writeObject(date);
            outputStream.flush();   //缓冲流
            outputStream.close();   //关闭流

            bytes = outputStream.toByteArray();
        } catch (Exception e) {
            System.out.println("Date序列化失败");
        }
        return bytes;
    }

    public static Date getDateFromByte(byte[] bytes) {
        //反序列化
        ByteArrayInputStream stream1 = new ByteArrayInputStream(bytes);
        ObjectInputStream stream2 = null;
        try {
            stream2 = new ObjectInputStream(stream1);
            Object o = stream2.readObject();
            return (Date) o;
        } catch (Exception e) {
            System.out.println("Date反序列化失败");
        }
        return null;
    }

    //UUid
    public static byte[] getByteFromUUID(UUID uuid) {
        byte[] bytes = null;
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(5120);
            ObjectOutputStream stream = new ObjectOutputStream(outputStream);
            stream.writeObject(uuid);
            outputStream.flush();   //缓冲流
            outputStream.close();   //关闭流

            bytes = outputStream.toByteArray();
        } catch (Exception e) {
            System.out.println("UUID序列化失败");
        }
        return bytes;
    }

    public static UUID getUUIDFromByte(byte[] bytes) {
        //反序列化
        ByteArrayInputStream stream1 = new ByteArrayInputStream(bytes);
        ObjectInputStream stream2 = null;
        try {
            stream2 = new ObjectInputStream(stream1);
            Object o = stream2.readObject();
            return (UUID) o;
        } catch (Exception e) {
            System.out.println("UUID反序列化失败");
        }
        return null;
    }

    //Integer
    public static byte[] getByteFromInteger(Integer n) {
        byte[] bytes = null;
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(5120);
            ObjectOutputStream stream = new ObjectOutputStream(outputStream);
            stream.writeObject(n);
            outputStream.flush();   //缓冲流
            outputStream.close();   //关闭流

            bytes = outputStream.toByteArray();
        } catch (Exception e) {
            System.out.println("Integer序列化失败");
        }
        return bytes;
    }

    public static Integer getIntegerFromByte(byte[] bytes) {
        //反序列化
        ByteArrayInputStream stream1 = new ByteArrayInputStream(bytes);
        ObjectInputStream stream2 = null;
        try {
            stream2 = new ObjectInputStream(stream1);
            Object o = stream2.readObject();
            return (Integer) o;
        } catch (Exception e) {
            System.out.println("Integer反序列化失败");
        }
        return null;
    }
}
